package datastream.api.datasource;

import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.streaming.api.datastream.DataStreamSink;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.source.SourceFunction;

public class UserDefined {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(2);

        DataStreamSource<String> source = env.addSource(new UserDefinedSourceFunction());

        SingleOutputStreamOperator<String> transformation = source.map(new MapFunction<String, String>() {
            @Override
            public String map(String value) throws Exception {
                return value.split(" ")[0] + "-user-defined-source";
            }
        });

        DataStreamSink<String> sink = transformation.print();

        env.execute();
    }

    private static class  UserDefinedSourceFunction implements SourceFunction<String> {

        private volatile boolean isCancel = false;

        // 该方法仅被调用一次
        // 通过 while 循环模拟无界流
        @Override
        public void run(SourceContext<String> ctx) throws Exception {
            int i = 0;
            while (!this.isCancel) {
                i++;
                ctx.collect(i + "");
                Thread.sleep(1000);
            }
        }

        // Flink 程序停止时，该方法被调用，实现停止从外部数据源读取数据的逻辑
        // 通过标记 isCancel 结束 run 方法的循环逻辑
        @Override
        public void cancel() {
            this.isCancel = true;
        }
    }
}


